gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scemflib/SCBrkEMF.cpp

    //Download by http://www.NewXing.com
/*
*	This file is part of the EMFexplorer projet.
*	Copyright (C) 2004 Smith Charles.
*
*	This library is free software; you can redistribute it and/or
*	modify it under the terms of the GNU Lesser General Public
*	License as published by the Free Software Foundation; either
*	version 2.1 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with this library; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
*
*	Extension: for commercial use, apply the Equity Public License, which
*	adds to the normal terms of the GLPL a condition of donation to the author.
*   If you are interested in support for this source code,
*   contact Smith Charles <smith.charles@free.fr> for more information.
*/


#include "stdafx.h"
#include "SCBrkEMF.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

SCBrkEMF::SCBrkEMF():
	SCBrkTarget(),
	//got from outside
	m_hPlayDC(NULL),
	m_pPlayData(NULL),
	m_lpPlayRect(NULL),
	m_lpEnumHandleTable(NULL),
	m_nEnumNbObjs(0),
	//inside
	m_nCurRec(0),
	m_nCbSpan(0),
	m_ErrorRec(0),
	m_bStop(FALSE)
{
}

SCBrkEMF::~SCBrkEMF()
{
}

void SCBrkEMF::SCResetCracker()
{
}


//////////////////////////////////////////////////////////////////////
// Events methods
//////////////////////////////////////////////////////////////////////
SC_BRKRESULT SCBrkEMF::OnEmfHEADER()
{
	// TRACE0("**EMR_HEADER\n");

	// DONE_EMF: Place code here to handle EMF record
	if (m_pIBrkCallBack)
	{
		ASSERT(m_pRecord);
		long lRes = m_pIBrkCallBack->OnSCBrkMaxPos(((ENHMETAHEADER*)m_pRecord)->nRecords);
		if (0==lRes)
			return SC_BRK_STOPBREAKING;
	}
	
	return SC_BRK_NOERROR;
}

// Derived classes should implement this to handle unmapped records
SC_BRKRESULT SCBrkEMF::OnBrkUNKRecord(long lMsg)
{
	// TRACE0("**OnBrkUNKRecord\n");
	SCPlayRecord(); // by default, let Windows manage it
	return SC_BRK_NOERROR;
}


//////////////////////////////////////////////////////////////////////
// Events dispatcher
//////////////////////////////////////////////////////////////////////
SC_BRKRESULT SCBrkEMF::SCDispatchEMFRecord(ENHMETARECORD FAR *lpEnhMetaRecord, HANDLETABLE FAR *lpHandleTable)	
{
	ASSERT(lpEnhMetaRecord);
	if (m_bStop)
		return SC_BRK_STOPBREAKING;

	// private initialization
	m_pRecord = lpEnhMetaRecord;
	m_lpEnumHandleTable = lpHandleTable;

#if 1
	// Record-level control needed (m_pIBrkCallBack!=NULL)

	// TRACE0("\nbegin SCBrkEMF::SCDispatchEMFRecord\n");
	SC_BRKRESULT error(SC_BRK_NOERROR);

	// Prolog:
	// if per-record initialization fails, stop metafile enumeration
	if (error=SCBeginRecordBreak())
		return error;
	
	// Dispatch:
	if (error = this->OnBrkRecord((long)lpEnhMetaRecord->iType))
		return error;
	
	// Epilog:
	// if per-record termination fails, stop metafile enumeration
	error = SCEndRecordBreak();
	
	// TRACE0("end SCBrkEMF::SCDispatchEMFRecord\n");
	return error;
#else
	// speed needed
	return this->OnBrkRecord((long)lpEnhMetaRecord->iType);
#endif
}

// Implementation
//

long SCBrkEMF::SCGetRecordSize() const
{
	if (m_pRecord)
		return ((EMR*)m_pRecord)->nSize;
	return 0;
}

//////////////////////////////////////////////////////////////////////
// Starter methods
//////////////////////////////////////////////////////////////////////
int CALLBACK SCBrkEMF::sEnumEMFCallbak(HDC hDC,HANDLETABLE FAR *lpHandleTable, ENHMETARECORD FAR *lpEnhMetaRecord,	
							 int nObj, LPARAM lpData)
{
	SC_BRKRESULT error(SC_BRK_NOERROR);
	SCBrkEMF* pBrkTarget = (SCBrkEMF*)lpData;

	// nObj was stored before enumeration started

	ASSERT(pBrkTarget);
	if (error = pBrkTarget->SCDispatchEMFRecord(lpEnhMetaRecord, lpHandleTable))
	{
		pBrkTarget->SCSetRecordError(error);
		return 0;
	}

	return 1;
}

SC_BRKRESULT SCBrkEMF::SCBreakMetafile(HDC hdc, HENHMETAFILE hemf, LPVOID lpData,
										 CONST RECT *lpRect)
{
	ASSERT(hemf);

	// Setup permanent app data
	SC_BRKRESULT error = SCBeginBreak(hdc, lpData, lpRect);

	// Enumerate
	if (SC_BRK_NOERROR == error)
	{
		ENHMETAHEADER EmfHeader;
		if (::GetEnhMetaFileHeader(hemf, sizeof(ENHMETAHEADER), &EmfHeader))
		{
			m_nEnumNbObjs = EmfHeader.nHandles;
		} else
			return SC_BRK_BADDATASOURCE;
		
		int nEmumRes = ::EnumEnhMetaFile(m_hPlayDC, hemf, (ENHMFENUMPROC)SCBrkEMF::sEnumEMFCallbak, (void*)this, lpRect);
		
		SCEndBreak();

		if (!nEmumRes)
		{// error !?
			// We should call GetLastError. But most of the time it returns 0 (meaning "no error").
			error = m_ErrorRec = SC_BRK_ENUMERATIONFAILED;
		}
	}

	return error;
}

//////////////////////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////////////////////

SC_BRKRESULT SCBrkEMF::SCBeginBreak(HDC hdc, LPVOID lpData, CONST RECT *lpRect)
{
	SC_BRKRESULT error = SCInitBreak();

	//got from outside
	m_hPlayDC = hdc;
	m_pPlayData = lpData;
	m_lpPlayRect = lpRect;
	m_lpEnumHandleTable = NULL;
	m_nEnumNbObjs = 0;

	//inside
	m_pRecord = NULL;
	m_nCurRec = 0;
	m_bStop = FALSE;
	return error;
}

void SCBrkEMF::SCEndBreak()
{
	if (!m_bStop && m_pIBrkCallBack) 	
		m_pIBrkCallBack->OnSCBrkPos(m_nCurRec);
}

// called for per-record initialization
SC_BRKRESULT SCBrkEMF::SCBeginRecordBreak()
{
	if (m_bStop)
		return SC_BRK_STOPBREAKING;

	m_nCurRec++;
	return SC_BRK_NOERROR;
}

// play the current record
void SCBrkEMF::SCPlayRecord()
{
	ASSERT(m_pRecord);
	::PlayEnhMetaFileRecord(m_hPlayDC, m_lpEnumHandleTable, (ENHMETARECORD*)m_pRecord, m_nEnumNbObjs);
}

// play a given record (generally a copy)
void SCBrkEMF::SCPlayRecord(void* pRec)
{
	ASSERT(pRec);
	::PlayEnhMetaFileRecord(m_hPlayDC, m_lpEnumHandleTable, (ENHMETARECORD*)pRec, m_nEnumNbObjs);
}

// play the current record in another DC
void SCBrkEMF::SCPlayRecord(HDC hDC)
{
	ASSERT(m_pRecord);
	ASSERT(hDC);
	::PlayEnhMetaFileRecord(hDC, m_lpEnumHandleTable, (ENHMETARECORD*)m_pRecord, m_nEnumNbObjs);
}

// play a given record record in another DC
void SCBrkEMF::SCPlayRecord(HDC hDC, void* pRec)
{
	ASSERT(pRec);
	ASSERT(hDC);
	::PlayEnhMetaFileRecord(hDC, m_lpEnumHandleTable, (ENHMETARECORD*)pRec, m_nEnumNbObjs);
}


// play a given record (generally a copy), and free memory
void SCBrkEMF::SCPlayRecordAndFree(void* pRec)
{
	ASSERT(pRec);
	::PlayEnhMetaFileRecord(m_hPlayDC, m_lpEnumHandleTable, (ENHMETARECORD*)pRec, m_nEnumNbObjs);
	SCFreeCloneRecord(pRec);
}


// called for per-record termination
SC_BRKRESULT SCBrkEMF::SCEndRecordBreak()
{
	SC_BRKRESULT error(SC_BRK_NOERROR);
	if (m_bStop)
		return SC_BRK_STOPBREAKING;

	if (m_pIBrkCallBack && m_nCbSpan && !(m_nCurRec % m_nCbSpan)) 
	{	
		long lRes = m_pIBrkCallBack->OnSCBrkPos(m_nCurRec);
		if (0==lRes)
			return SC_BRK_STOPBREAKING;
	}
	return error;
}


//////////////////////////////////////////////////////////////////////
// Message map
//////////////////////////////////////////////////////////////////////
SC_BEGIN_MESSAGE_MAP(SCBrkEMF, SCBrkTarget)
ON_VECTRECORD(SCEMF_HEADER, OnEmfHEADER)
SC_END_MESSAGE_MAP()